package com.xiaoshuidi.cloud.module.finance.service.finance.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.mybatis.core.util.MyBatisUtils;
import com.xiaoshuidi.cloud.module.finance.controller.admin.finance.vo.reconciliation.FinanceReconciliationManualCheckReqVO;
import com.xiaoshuidi.cloud.module.finance.controller.admin.finance.vo.reconciliation.FinanceReconciliationPageReqVO;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.finance.FinanceMoneyFlowDO;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.finance.FinanceReconciliationLogDO;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.finance.FinanceYinlianReconciliationPair;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.finance.YinlianReconciliationDO;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.order.PayOrderDO;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.finance.FinanceMoneyFlowMapper;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.finance.FinanceReconciliationLogMapper;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.finance.YinlianReconciliationMapper;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.notify.order.PayOrderMapper;
import com.xiaoshuidi.cloud.module.finance.service.finance.FinanceReconciliationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.List;

@Slf4j
@Service
public class FinanceReconciliationServiceImpl implements FinanceReconciliationService {
    @Resource
    private FinanceReconciliationLogMapper financeReconciliationLogMapper;
    @Resource
    private FinanceMoneyFlowMapper financeMoneyFlowMapper;

    @Resource
    private YinlianReconciliationMapper yinlianReconciliationMapper;
    @Resource
    private PayOrderMapper payOrderMapper;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Override
    public List<FinanceReconciliationLogDO> date(LocalDate date) {
        return financeReconciliationLogMapper.selectList(new QueryWrapper<FinanceReconciliationLogDO>()
                .eq("settlement_date", date)
                .select("pay_channel",
                        "settlement_date",
                        "sum(total_amount) as total_amount",
                        "sum(total_count) as total_count",
                        "sum(channel_total_amount) as channel_total_amount",
                        "sum(channel_total_count) as channel_total_count",
                        "sum(total_service_charge) as total_service_charge",
                        "if(sum(if(success = 1, 0, 1)) > 0, 0, 1) as success")
                .groupBy("pay_channel",
                        "settlement_date")
        );
    }

    @Override
    public PageResult<FinanceYinlianReconciliationPair> getPage(FinanceReconciliationPageReqVO reqVO) {
        IPage<FinanceYinlianReconciliationPair> mpPage = MyBatisUtils.buildPage(reqVO);
        financeReconciliationLogMapper.getNewPage(reqVO, mpPage);
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }

    @Override
    public void manualCheck(FinanceReconciliationManualCheckReqVO reqVO) {
        transactionTemplate.executeWithoutResult(status -> {
            FinanceMoneyFlowDO financeMoneyFlowDO = financeMoneyFlowMapper.getByFlowNo(reqVO.getFlowNo());
            if (financeMoneyFlowDO != null && StringUtils.hasText(financeMoneyFlowDO.getMerchantOrderId())) {
                payOrderMapper.manualCheck(financeMoneyFlowDO.getMerchantOrderId(), PayOrderDO.builder()
                        .checked(1)
                        .checkFailedRemark(reqVO.getRemark())
                        .build());
            }
            YinlianReconciliationDO yinlianReconciliationDO =
                    yinlianReconciliationMapper.selectOne(YinlianReconciliationDO::getMerOrderId
                    , reqVO.getMerchantOrderId());
            if (ObjectUtil.isNotEmpty(yinlianReconciliationDO)) {
                //修改对账表
                yinlianReconciliationMapper.updateById(YinlianReconciliationDO.builder()
                        .id(yinlianReconciliationDO.getId())
                        .checked(1)
                        .checkFailedRemark(reqVO.getRemark())
                        .build());
                FinanceReconciliationPageReqVO requestVo = new FinanceReconciliationPageReqVO();
                requestVo.setDate(yinlianReconciliationDO.getSettleDate());
                int thisSystemCheckedCount = financeReconciliationLogMapper.getThisSystemCheckedCount(requestVo);
                int notThisSystemCheckedCount = financeReconciliationLogMapper.getNotThisSystemCheckedCount(requestVo);
                //获取当前租户下对账记录
                FinanceReconciliationLogDO financeReconciliationLogDO =
                        financeReconciliationLogMapper.selectOne(new QueryWrapper<FinanceReconciliationLogDO>()
                                .eq("pay_channel", "银联")
                                .eq("settlement_date", yinlianReconciliationDO.getSettleDate()));
                if (ObjectUtil.isNotEmpty(financeReconciliationLogDO)
                        && thisSystemCheckedCount + notThisSystemCheckedCount
                        >= financeReconciliationLogDO.getChannelTotalCount()) {
                    //全部异常处理完成修改为对账成功
                    financeReconciliationLogMapper.updateById(FinanceReconciliationLogDO.builder()
                            .id(financeReconciliationLogDO.getId())
                            .success(true)
                            .build());
                }

            }
        });


    }

    @Override
    public List<FinanceReconciliationLogDO> calendar(LocalDate date) {
        return financeReconciliationLogMapper.selectList(new QueryWrapper<FinanceReconciliationLogDO>()
                .between("settlement_date", date.withDayOfMonth(1), date.withDayOfMonth(date.lengthOfMonth()))
                        .gt("total_amount", 0)
                .select("settlement_date")
                .groupBy("settlement_date")
        );
    }
}
